package com.zzvcom.office.docx4jutil;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.openhtmltopdf.css.style.CalculatedStyle;
import com.openhtmltopdf.render.BlockBox;
import com.openhtmltopdf.render.Box;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.docx4j.UnitsOfMeasurement;
import org.docx4j.convert.in.xhtml.XHTMLImporterImpl;
import org.docx4j.convert.in.xhtml.renderer.Docx4JFSImage;
import org.docx4j.convert.in.xhtml.renderer.Docx4jUserAgent;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.wml.Drawing;
import org.docx4j.wml.P;
import org.docx4j.wml.R;

import java.awt.*;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * docx4j处理类
 */
@Slf4j
public class Utils {


    public static void commonProcessBackgroundImages(Box box, P currentP, XHTMLImporterImpl xhtmlImporter) {
        BlockBox blockBox= (BlockBox) box;
        //yujikuan add

        List<CalculatedStyle.BackgroundContainer> backgroundImages = blockBox.getStyle().getBackgroundImages();
        if (CollUtil.isNotEmpty(backgroundImages)) {
            Rectangle contentBounds = box.getContentAreaEdge(box.getAbsX(), box.getAbsY(),
                    xhtmlImporter.getRenderer().getLayoutContext());

            Long cy = contentBounds.height == 0 ? null :
                    UnitsOfMeasurement.twipToEMU(dotsToTwip(contentBounds.height));
            Long cx = contentBounds.width == 0 ? null :
                    UnitsOfMeasurement.twipToEMU(dotsToTwip(contentBounds.width));

            for (CalculatedStyle.BackgroundContainer backgroundImage : backgroundImages) {

                R r = Utils.processBackgroundHelper(xhtmlImporter.getWordMLPackage(), backgroundImage, xhtmlImporter.getRenderer().getDocx4jUserAgent(),
                        cx,cy
                );
                if (r != null) {
                    if (currentP != null) {
                        currentP.getContent().add(r);
                    }
                }
            }
        }
    }

    public static R processBackgroundHelper(WordprocessingMLPackage wordMLPackage, CalculatedStyle.BackgroundContainer backgroundImage,
                                            Docx4jUserAgent docx4jUserAgent,
                                            Long cx, Long cy) {
        //
        if (CalculatedStyle.BackgroundImageType.URI != backgroundImage.type) {
            log.warn("背景图片仅仅支持uri,meet={}", backgroundImage);
            return null;
        }
        byte[] imageBytes;
        String stringValue = backgroundImage.imageGradientOrNone.getStringValue();
        if (StrUtil.isBlank(stringValue)) {
            return null;
        }
        if (stringValue.startsWith("data:image")) {
            int commaPos = stringValue.indexOf(",");
            String base64String = stringValue.substring(commaPos + 1);
            log.debug(base64String);
            try {
                imageBytes = Base64.decodeBase64(base64String.getBytes(StandardCharsets.UTF_8));
                return viewImage(wordMLPackage, imageBytes, cx, cy);
            } catch (Exception e) {
                log.error("base64 addBackgroundImage", e);
            }
        } else {
            String url = stringValue;
            log.info("url={}", url);
            // Workaround for cannot resolve the URL C:\... with base URL file:/C:/...
            // where @src points to a raw file path
            if (url.substring(1, 2).equals(":")) {
                url = "file:/" + url;
            }
            Docx4JFSImage docx4JFSImage = docx4jUserAgent.getDocx4JImageResource(url);
            if (docx4JFSImage == null) {
                // in case of wrong URL - docx4JFSImage will be null
                log.error("Couldn't fetch url " + url);
            } else {
                imageBytes = docx4JFSImage.getBytes();
                try {
                    return viewImage(wordMLPackage, imageBytes, cx, cy);
                } catch (Exception e) {
                    log.error("url={}", url);
                    log.error("url e", e);
                }
            }
        }
        return null;
    }

    private static R viewImage(WordprocessingMLPackage wordMLPackage, byte[] imageBytes, Long cx, Long cy) throws Exception {
        BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, imageBytes);
        long docPrId = wordMLPackage.getDrawingPropsIdTracker().generateId();
        Inline inline = null;
        if (cx != null && cy != null) {
            inline = imagePart.createImageInline(null, "", docPrId, 1, cx, cy, false);
        } else if (cx != null) {
            inline = imagePart.createImageInline(null, "", docPrId, 1, cx, false);
        }else {
            inline = imagePart.createImageInline(null, "", docPrId, 1, false);
        }
        // Now add the inline in w:p/w:r/w:drawing
        R run = Context.getWmlObjectFactory().createR();
        Drawing drawing = Context.getWmlObjectFactory().createDrawing();
        run.getContent().add(drawing);
        drawing.getAnchorOrInline().add(inline);
        return run;
    }


    public static float dotsToTwip(float dots) {
        return dots * 72f / (UnitsOfMeasurement.DPI);
        // Java2D DPI/
    }
}
